import os.path
import time

from PySide6.QtCore import QThread, Signal, QProcess, Slot
from PySide6.QtWidgets import QWidget, QMessageBox

import zz.zz_str
from zz import zz_return, zz_log, zz_mitmproxy, zz_gui, zz_code

log = zz_log.of()


class ZZ_Win(QWidget):
    def __init__(self, proxy: zz_mitmproxy.ZZ_Proxy):
        super(ZZ_Win, self).__init__()
        # self.proxy = zz_mitmproxy.of(allow_hosts=['gzccic.com', 'lai-m.com'], file_path=__file__)
        self.proxy = proxy

        # 线程处理-mitmproxy是否开启成功
        self.handle_start_mitmproxy = zz_gui.ZZ_Thread()
        # 线程处理
        self.handle_listen_mitmproxy = zz_gui.ZZ_Thread()
        # 执行命令
        self.process = zz_gui.ZZ_Process(self)

    def get_mitmproxy_path(self):
        """
        获取mitmproxy安装目录
        """
        return zz_code.env("MITMPROXY_PATH", f'C:/Program Files/mitmproxy/bin')

    def start_mitmproxy(self) -> bool:
        """
        开启 mitmproxy
        """
        mitmproxy_dir = self.get_mitmproxy_path()
        mitmdump_path = f"{mitmproxy_dir}/mitmdump.exe"
        log.info(f"mitmproxy安装目录: {mitmproxy_dir}")
        log.info(f"mitmdump文件路径: {mitmdump_path}")
        if not os.path.exists(mitmdump_path):
            self.alert(f"找发现mitmdump，{mitmdump_path}")
            return False

        if not zz_mitmproxy.is_cert_installed():
            self.alert("证书未安装")
            return False

        # 关闭系统代理
        self.proxy.close_listen()
        # 启动mitmdump命令
        self.process.start('mitmdump', self.proxy.get_option())
        # 监听mitmdump是否启动成功
        self.handle_start_mitmproxy = zz_gui.ZZ_Thread()

        self.handle_start_mitmproxy.set_run_handle(self.__start_mitmproxy, self.proxy.port)
        self.handle_start_mitmproxy.finished.connect(self.start_mitmproxy_finished)
        self.handle_start_mitmproxy.set_timeout_max(3)
        self.handle_start_mitmproxy.start()
        return True

    def __start_mitmproxy(self, port):
        """
        mitmproxy检查启动状态
        """
        r = zz_return.of(20075, "启动未成功")
        if zz_mitmproxy.ZZ_Proxy.is_running(port):
            r = zz_return.of(0, "启动成功")
        # log.debug(f"start_mitmproxy: {r.to_json()}")
        return r

    @Slot(zz_return.Return)
    def start_mitmproxy_finished(self, r: zz_return.Return):
        """
        mitmproxy启动成功
        """
        self.handle_start_mitmproxy.stop()
        self.proxy.set_sys_proxy()
        self.handle_listen_mitmproxy = zz_gui.ZZ_Thread()
        self.handle_listen_mitmproxy.set_run_handle(self.__listen_mitmproxy)
        self.handle_listen_mitmproxy.finished.connect(self.listen_mitmproxy_finished)
        self.handle_listen_mitmproxy.start()

    def __listen_mitmproxy(self, data):
        """
        监听信息
        """
        r = zz_return.of(20101, "监控中")
        if zz_mitmproxy.exists_msg():
            r = zz_mitmproxy.get_msg()
        # log.debug(f'listen_mitmproxy: {r.to_json()}')
        return r

    @Slot(zz_return.Return)
    def listen_mitmproxy_finished(self, r: zz_return.Return):
        """
        监听信息成功
        """
        self.close_mitmproxy()

    def close_mitmproxy(self):
        self.proxy.close_listen()
        self.handle_start_mitmproxy.stop()
        self.handle_listen_mitmproxy.stop()

    def alert(self, msg):
        QMessageBox.warning(self, '提示', msg)


class ZZ_Thread(QThread):
    finished = Signal(zz_return.Return)  # 自定义信号，参数类型为 str

    def __init__(self, parent=None):
        """
        连接信号和槽
        self.worker.finished.connect(self.listen_ok)
        """
        super().__init__(parent)
        self.run_handle = None
        self.run_handle_data = None
        self.is_running = True
        self.wait_s = 2
        self.timeout_max = -1  # 超时次数，-1表示无限

    def set_timeout_max(self, timeout_max):
        """
        超时次数，-1表示无限
        """
        self.timeout_max = timeout_max

    def set_wait_s(self, wait_s: int):
        """
        等待时间，秒，例：2：2秒，0.1：100毫秒
        """
        self.wait_s = wait_s

    def set_run_handle(self, run_handle, data=None):
        """
        设置处理事件
        """
        self.run_handle = run_handle
        self.run_handle_data = data

    def run(self):
        r = zz_return.of(500, "异常")
        run_index = 0
        while self.is_running:
            run_index = run_index + 1
            r = self.run_handle(self.run_handle_data)
            if r.ok():
                break
            if self.timeout_max != -1 and run_index > self.timeout_max:
                r = zz_return.of(550, "处理超时")
                break

            time.sleep(self.wait_s)

        # 在这里执行一些耗时的操作
        self.finished.emit(r)  # 发射信号

    def stop(self):
        self.is_running = False
        while self.isRunning():
            # 等待进程结束
            time.sleep(1)
            break


class ZZ_Process(QProcess):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.readyReadStandardOutput.connect(self.__process_stdout)
        self.readyReadStandardError.connect(self.__process_err)
        self.msg_callback = None

    def bind_msg_callback(self, callback):
        self.msg_callback = callback

    def msg_handle(self, msg: str):
        log.info(msg)

        if zz.zz_str.contains(msg, 'INFO server.py'):
            return

        if self.msg_callback:
            self.msg_callback(msg)

    def __process_err(self):
        data = self.readAllStandardError()
        msg = bytes(data).decode("utf8")
        msg = msg.replace("\n", "")
        self.msg_handle(msg)

    def __process_stdout(self):
        data = self.readAllStandardOutput()
        msg = bytes(data).decode("utf8")
        msg = msg.replace("\n", "")
        self.msg_handle(msg)
